/*
 * This source code is part of TWaver 4.0
 *
 * Serva Software PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 * Copyright 2002 - 2011 Serva Software. All rights reserved.
 */

package demo.editor.chassis;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.List;

import javax.swing.JCheckBox;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;

import twaver.Card;
import twaver.Element;
import twaver.Equipment;
import twaver.Follower;
import twaver.Generator;
import twaver.Grid;
import twaver.MovableFilter;
import twaver.Node;
import twaver.ResizableFilter;
import twaver.ResizableNode;
import twaver.Shelf;
import twaver.Slot;
import twaver.TDataBox;
import twaver.TWaverConst;
import twaver.VisibleFilter;
import twaver.network.InteractionEvent;
import twaver.network.InteractionListener;
import twaver.network.TNetwork;
import twaver.table.TPropertySheet;
import twaver.table.TPropertySheetPane;
import twaver.tree.TTree;
import demo.DemoPane;
import demo.DemoUtil;
import demo.editor.EditablePopupMenuGenerator;
import demo.tree.TreePopupMenuGenerator;

public class ChassisEditorDemo extends DemoPane {

	private TDataBox box = new TDataBox("Equip Elements");
	private TNetwork network = new TNetwork(box);
	private TTree tree = new TTree(box);
	private TPropertySheet sheet = new TPropertySheet(box);

	public ChassisEditorDemo() {
		JSplitPane leftSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(tree), new TPropertySheetPane(sheet));
		JSplitPane mainSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftSplit, network);
		this.add(mainSplit, BorderLayout.CENTER);
		this.add(DemoUtil.createStatusLabel(network), BorderLayout.SOUTH);
		leftSplit.setDividerLocation(300);
		mainSplit.setDividerLocation(200);

		// set network
		network.setToolbarByName("ChassisEditorToolbar");
		network.setEnableDeleteWithKeyboard(true);
		network.setEnableCopyPasteWithKeyboard(true);

		final JCheckBox draggableAll = new JCheckBox("All Element Draggable", false);
		draggableAll.setFocusPainted(false);
		draggableAll.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				network.getCanvas().repaint();
			}
		});
		network.getToolbar().addSeparator();
		network.getToolbar().add(draggableAll);
		network.setResizableFilter(new ResizableFilter() {
			public boolean isResizable(Element element) {
				if (draggableAll.isSelected()) {
					return true;
				}
				if (element instanceof Slot || element instanceof Card) {
					return false;
				}
				if (element instanceof Shelf) {
					Shelf shelf = (Shelf) element;
					if (shelf.getParent() instanceof Shelf) {
						return false;
					}
				}
				return element instanceof ResizableNode;
			}
		});
		network.setPopupMenuGenerator(new EditablePopupMenuGenerator(network));
		network.clearMovableFilters();
		network.addMovableFilter(new MovableFilter() {
			public boolean isMovable(Element element) {
				if (draggableAll.isSelected()) {
					return true;
				}
				if (element instanceof Slot || element instanceof Card) {
					return false;
				}
				if (element instanceof Shelf) {
					Shelf shelf = (Shelf) element;
					if (shelf.getParent() instanceof Shelf) {
						return false;
					}
				}
				return true;
			}
		});
		network.setElementLabelGenerator(new Generator() {
			public Object generate(Object object) {
				if (object instanceof Equipment) {
					return null;
				} else {
					return ((Element) object).getName();
				}
			}
		});
		network.addVisibleFilter(new VisibleFilter() {
			public boolean isVisible(Element element) {
				if (element instanceof Equipment) {
					Equipment equipment = (Equipment) element;
					return equipment.isExist();
				}
				return true;
			}
		});
		// set tree
		tree.setEnsureVisibleOnSelected(true);
		tree.setElementDraggable(true);
		tree.setPopupMenuGenerator(new TreePopupMenuGenerator(tree));

		// set propertySheet
		sheet.setEditable(true);

		// init box
		try {
			box.parse("/demo/editor/chassis/Template_Rack.xml");
		} catch (IOException e) {
			e.printStackTrace();
		}
		Grid grid = new Grid();
		grid.setLocation(130, 400);
		grid.setSize(440, 240);
		grid.setRowCount(2);
		grid.setColumnCount(2);
		box.addElement(grid);

		addGrid(grid, 0, 0, 2, 2, 10, 0, 40, 0, 90, new Color(100, 150, 0));
		addGrid(grid, 0, 0, 2, 2, 10, 30, 0, 110, 0, new Color(100, 150, 0));
		addGrid(grid, 0, 1, 1, 2, 10, 0, 50, 0, 0, null);
		addGrid(grid, 0, 1, 2, 2, 10, 50, 0, 0, 0, new Color(0, 100, 100));
		addGrid(grid, 1, 0, 2, 2, 10, 0, 0, 0, 80, null);
		addGrid(grid, 1, 0, 1, 2, 10, 0, 0, 120, 0, new Color(150, 100, 0, 200));
		addGrid(grid, 1, 1, 2, 3, 10, 0, 0, 0, 0, Color.GRAY);
		

		box.getUndoRedoManager().setLimit(200);
		network.setEnableUndoRedoWithKeyboard(true);

		box.addElementPropertyChangeListener(new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent evt) {
				if (!(evt.getSource() instanceof Follower)) {
					return;
				}
				if (TWaverConst.PROPERTYNAME_PARENT.equals(evt.getPropertyName())) {
					Follower follower = (Follower) evt.getSource();
					if (follower.getHost() != follower.getParent()) {
						follower.setHost((Node) follower.getParent());
					}
				} else if (TWaverConst.PROPERTYNAME_CHILDREN.equals(evt.getPropertyName())) {
					Follower follower = (Follower) evt.getNewValue();
					if (follower != null && follower.getHost() != follower.getParent()) {
						follower.setHost((Node) follower.getParent());
					}
				} else if (TWaverConst.PROPERTYNAME_EQUIPCOUNT.equals(evt.getPropertyName())) {
					Object source = evt.getSource();
					if (source instanceof Shelf) {
						Shelf shelf = (Shelf) source;
						if (shelf.getAllFollowers() == null || shelf.getAllFollowers().size() == 0) {
							for (int i = 0; i < shelf.getEquipCount(); i++) {
								Slot slot = new Slot();
								box.addElement(slot);
								slot.setHost(shelf);
								slot.setParent(shelf);
								slot.setEquipIndex(i);
								slot.setName("Slot" + i);
								Card card = new Card();
								box.addElement(card);
								card.setHost(slot);
								card.setParent(slot);
								card.setName("Card" + i);
							}
						}
					} else if (source instanceof Slot) {
						Slot slot = (Slot) source;
						if (slot.getAllFollowers() == null || slot.getAllFollowers().size() == 0) {
							for (int i = 0; i < slot.getEquipCount(); i++) {
								Slot subSlot = new Slot();
								box.addElement(subSlot);
								subSlot.setHost(slot);
								subSlot.setParent(slot);
								subSlot.setEquipIndex(i);
								subSlot.setName("Slot" + i);
							}
						}
					}
				}
			}
		});

		installGridListener();
	}

	private void addGrid(Grid host, int rowIndex, int columnIndex, int rowCount, int columnCount, int padding, int top, int bottom, int left, int right, Color color) {
		Grid grid = new Grid();
		grid.setHost(host);
		if (color != null) {
			grid.putRenderColor(color);
		}
		grid.setRowCount(rowCount);
		grid.setColumnCount(columnCount);
		grid.setRowIndex(rowIndex);
		grid.setColumnIndex(columnIndex);
		grid.setFollowerPadding(padding);
		grid.setFollowerPaddingTop(top);
		grid.setFollowerPaddingBottom(bottom);
		grid.setFollowerPaddingLeft(left);
		grid.setFollowerPaddingRight(right);
		box.addElement(grid);
	}

	private void installGridListener() {
		network.addInteractionListener(new InteractionListener() {
			public void interactionPerformed(InteractionEvent event) {
				Element element = box.getLastSelectedElement();
				if (element instanceof Grid) {
					if (event.getType() == InteractionEvent.ELEMENT_SMOOTH_MOVED) {
						Point location = network.getLogicalPoint(event.getMouseEvent().getPoint());
						Grid grid = (Grid) element;
						List elements = network.getElementsLogicalAt(location);
						elements.remove(element);
						int size = elements.size();
						if (size > 0) {
							Element bottomElement = (Element) elements.get(0);
							if (bottomElement instanceof Grid) {
								Grid host = (Grid) bottomElement;
								Insets padding = host.getPadding();
								Insets border = host.getBorder();
								if (grid.getHost() != host) {
									grid.setHost(host);
								}
								int cols = host.getColumnCount();
								int rows = host.getRowCount();
								for (int i = 0; i < cols; i++) {
									for (int j = 0; j < rows; j++) {
										Rectangle rect = host.getCellRect(i, j);
										if (padding != null) {
											rect.width = rect.width + padding.left + padding.right;
											rect.height = rect.height + padding.top + padding.bottom;
											rect.x = rect.x - padding.left;
											rect.y = rect.y - padding.top;
										}
										if (border != null) {
											if (i == 0) {
												rect.width = rect.width + border.left;
												rect.x = rect.x - border.left;
											}
											if (i == cols - 1) {
												rect.width = rect.width + border.right;
											}
											if (j == 0) {
												rect.height = rect.height + border.top;
												rect.y = rect.y - border.top;
											}
											if (j == rows - 1) {
												rect.height = rect.height + border.bottom;
											}
										}
										if (rect.contains(location)) {
											grid.setColumnIndex(i);
											grid.setRowIndex(j);
											return;
										}
									}
								}
								return;
							}
						}
						grid.setHost(null);
					}
				}
			}
		});
	}

}